package code

import java.nio.ByteOrder

import io.netty.buffer.ByteBuf
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.MessageToByteEncoder
import io.netty.util.internal.ObjectUtil
import utils.ByteUtils

class MyLengthFieldPrepender
/**
 * Creates a new instance.
 *
 * @param byteOrder         the [ByteOrder] of the length field
 * @param lengthAdjustment  the compensation value to add to the value
 * of the length field
 * @param lengthIncludesLengthFieldLength
 * if `true`, the length of the prepended
 * length field is added to the value of the
 * prepended length field.
 */
(
        private val byteOrder: ByteOrder,
        private val lengthAdjustment: Int, private val lengthIncludesLengthFieldLength: Boolean) : MessageToByteEncoder<ByteBuf>() {
    private val lengthFieldLength = 4

    /**
     * Creates a new instance.
     *
     * @param lengthIncludesLengthFieldLength
     * if `true`, the length of the prepended
     * length field is added to the value of the
     * prepended length field.
     */
    @JvmOverloads constructor(lengthIncludesLengthFieldLength: Boolean = false) : this(0, lengthIncludesLengthFieldLength) {}

    /**
     * Creates a new instance.
     *
     * @param lengthAdjustment  the compensation value to add to the value
     * of the length field
     * @param lengthIncludesLengthFieldLength
     * if `true`, the length of the prepended
     * length field is added to the value of the
     * prepended length field.
     *
     * @throws IllegalArgumentException
     * if `lengthFieldLength` is not 1, 2, 3, 4, or 8
     */
    @JvmOverloads constructor(lengthAdjustment: Int, lengthIncludesLengthFieldLength: Boolean = false) : this(ByteOrder.BIG_ENDIAN, lengthAdjustment, lengthIncludesLengthFieldLength) {}

    init {
        ObjectUtil.checkNotNull(byteOrder, "byteOrder")
    }

    @Throws(Exception::class)
    override fun encode(ctx: ChannelHandlerContext, msg: ByteBuf, out: ByteBuf) {
        var length = msg.readableBytes() + lengthAdjustment
        if (lengthIncludesLengthFieldLength) {
            length += lengthFieldLength
        }

        if (length < 0) {
            throw IllegalArgumentException(
                    "Adjusted frame length ($length) is less than zero")
        }

        when (lengthFieldLength) {
            1 -> {
                if (length >= 256) {
                    throw IllegalArgumentException(
                            "length does not fit into a byte: " + length)
                }
                out.writeByte(length.toByte().toInt())
            }
            4 -> ByteUtils.writeVariaInt(length, out)
            8 -> ByteUtils.writeVariaLong(length.toLong(), out)
            else -> throw Error("should not reach here")
        }//            out.writeInt(length);
        //            out.writeLong(length);

        out.writeBytes(msg, msg.readerIndex(), msg.readableBytes())
    }

    @Throws(Exception::class)
    override fun allocateBuffer(ctx: ChannelHandlerContext, msg: ByteBuf?, preferDirect: Boolean): ByteBuf {
        return super.allocateBuffer(ctx, msg, preferDirect).order(byteOrder)
    }
}
/**
 * Creates a new instance.
 *
 *
 */
/**
 * Creates a new instance.
 *
 * @param lengthAdjustment  the compensation value to add to the value
 * of the length field
 *
 * @throws IllegalArgumentException
 * if `lengthFieldLength` is not 1, 2, 3, 4, or 8
 */
